use crate::{Bbox, YoloData};

pub fn bbox2yolo(bbox: Bbox, image_size: (i32, i32), file_path: &str) -> Result<YoloData, Box<dyn std::error::Error>> {
    let (image_width, image_height) = image_size;

    // 验证图像尺寸不为零
    if image_width <= 0 || image_height <= 0 {
        return Err(format!("Image width and height must be positive in file: {} ({:?})", file_path, image_size).into());
    }

    // 验证边界框坐标有效性
    if bbox.x1 < 0 || bbox.y1 < 0 || bbox.x2 < 0 || bbox.y2 < 0 {
        return Err(format!("Bounding box coordinates must be non-negative in file: {} ({:?})", file_path, image_size).into());
    }

    if bbox.x1 >= image_width || bbox.x2 >= image_width ||
        bbox.y1 >= image_height || bbox.y2 >= image_height {
        return Err(format!("Bounding box coordinates exceed image dimensions {:?} in file: {} ({:?})", bbox, file_path, image_size).into());
    }

    if bbox.x1 >= bbox.x2 || bbox.y1 >= bbox.y2 {
        return Err(format!("Invalid bounding box: x1 must be less than x2 and y1 must be less than y2 in file: {} ({:?})", file_path, image_size).into());
    }

    let x_center = (((bbox.x1 + bbox.x2) as f32 / 2.0 / image_width as f32) * 1_000_000.0).round() / 1_000_000.0;
    let y_center = (((bbox.y1 + bbox.y2) as f32 / 2.0 / image_height as f32) * 1_000_000.0).round() / 1_000_000.0;
    let width = ((bbox.x2 - bbox.x1) as f32 / image_width as f32 * 1_000_000.0).round() / 1_000_000.0;
    let height = ((bbox.y2 - bbox.y1) as f32 / image_height as f32 * 1_000_000.0).round() / 1_000_000.0;

    Ok(YoloData {
        x_center,
        y_center,
        width,
        height,
    })
}